package cn.itcast.nems.studentrecord.service.impl.studentrecord;

import cn.itcast.nems.base.dao.entity.E2Clazz;
import cn.itcast.nems.base.dao.mapper.E2ClazzMapper;
import cn.itcast.nems.common.account.AccountHolder;
import cn.itcast.nems.common.tenant.TenantInfo;
import cn.itcast.nems.manager.msas.MsasManager;
import cn.itcast.nems.studentrecord.bo.StudentRecordInvoiceBo;
import cn.itcast.nems.studentrecord.dao.entity.StudentRecordInvoice;
import cn.itcast.nems.studentrecord.dao.mapper.StudentRecordInvoiceMapper;
import cn.itcast.nems.studentrecord.service.StudentRecordInvoiceService;
import cn.itcast.nems.studentrecord.service.studentrecord.StudentRecordService;
import cn.itcast.nems.studentrecord.vo.StudentRecordInvoiceVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.itcast.msas.sdk.acm.domain.AccountDto;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static cn.itcast.nems.journal.util.TransferUtils.*;


@Service
@Slf4j
@RequiredArgsConstructor
public class StudentRecordInvoiceServiceImpl implements StudentRecordInvoiceService {

    private final StudentRecordInvoiceMapper studentRecordInvoiceMapper;
    private final StudentRecordService studentRecordService;
    private final MsasManager msasManager;
    private final E2ClazzMapper e2ClazzMapper;

    private StudentRecordInvoiceVo mapToVo(StudentRecordInvoice studentRecordInvoice) {
        return new StudentRecordInvoiceVo(
                studentRecordInvoice.getId(),
                studentRecordInvoice.getInvoiceNo(),
                studentRecordInvoice.getInvoiceHeader(),
                studentRecordInvoice.getInvoiceBalance(),
                formatPrice(studentRecordInvoice.getInvoiceBalance()),
                studentRecordInvoice.getModifiedBy(),
                null, null,
                studentRecordInvoice.getModifiedDatetime()
        );
    }

    private void putModifiedByName(List<StudentRecordInvoiceVo> list) {
        if (list == null || list.isEmpty()) {
            return;
        }
        var modifiedBySet = list.stream()
                .map(StudentRecordInvoiceVo::getModifiedBy)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
        if (modifiedBySet.isEmpty()) {
            return;
        }
        var accountMap = modifiedBySet.stream().map(msasManager::getAccount)
                .filter(Objects::nonNull).collect(Collectors.toMap(AccountDto::getUsername, x -> x));
        for (StudentRecordInvoiceVo studentRecordInvoiceVo : list) {
            var account = accountMap.get(studentRecordInvoiceVo.getModifiedBy());
            if (account != null) {
                studentRecordInvoiceVo.setModifiedByName(account.getName());
                studentRecordInvoiceVo.setModifiedByAndName(formatAccount(account));
            }
        }
    }

    private void checkPermission(Integer studentId, String studentRecordId) {
//        var groups = AccountHolder.getRequiredAccountEmployeeGroups();
//        var record = studentRecordService.queryById(studentRecordId);
//        Assert.notNull(record, "学籍不存在");
//        // tips: school 和 subject 信息为null，所以单独另外取
//        var clazz = e2ClazzMapper.selectOne(new QueryWrapper<>(new E2Clazz()).lambda().eq(E2Clazz::getClazzId, record.getClazzId()));
//        Assert.notNull(clazz, "学籍对应班级没有找到");
//        var subjectId = clazz.getSubjectId();
//        var schoolId = clazz.getSchoolCode();
//        //
//        boolean isAuthorized = false;
//        for (var group : groups.getGroupList()) {
//            isAuthorized = group.getSubjectIdList().contains(subjectId) && group.getSchoolCodeList().contains(schoolId);
//            if (isAuthorized) {
//                break;
//            }
//        }
//        Assert.isTrue(isAuthorized, "无权查看该学籍的发票信息");
//        // 不校验学生与学籍是否匹配，以节约性能
    }

    @Override
    public List<StudentRecordInvoiceVo> listStudentRecordInvoices(Integer studentId, String studentRecordId) {
        checkPermission(studentId, studentRecordId);
        var list = studentRecordInvoiceMapper.selectList(new QueryWrapper<StudentRecordInvoice>().lambda()
                .eq(StudentRecordInvoice::getStudentRecordId, studentRecordId)
                .eq(StudentRecordInvoice::getDeletedFlag, Boolean.FALSE)
                .orderByDesc(StudentRecordInvoice::getCreatedDatetime)
        ).stream().map(this::mapToVo).collect(Collectors.toList());
        putModifiedByName(list);
        return list;
    }

    @Override
    public Boolean createStudentRecordInvoice(Integer studentId, String studentRecordId, StudentRecordInvoiceBo studentRecordInvoiceBo) {
        if (!StringUtils.hasText(studentRecordInvoiceBo.getInvoiceNo())) {
            studentRecordInvoiceBo.setInvoiceNo("-");
        }
        checkPermission(studentId, studentRecordId);
        var now = LocalDateTime.now();
        var account = AccountHolder.getRequiredAccountInfo();
        var invoice = new StudentRecordInvoice();
        invoice.setStudentRecordId(studentRecordId);
        invoice.setInvoiceNo(studentRecordInvoiceBo.getInvoiceNo());
        invoice.setInvoiceHeader(studentRecordInvoiceBo.getInvoiceHeader());
        invoice.setInvoiceBalance(parsePrice(studentRecordInvoiceBo.getInvoiceBalanceFormatted()));
        invoice.setCreatedBy(account.getEmail());
        invoice.setModifiedBy(account.getEmail());
        invoice.setCreatedDatetime(now);
        invoice.setModifiedDatetime(now);
        invoice.setTenantId(TenantInfo.DEFAULT_TENANT_ID);
        invoice.setSubtenantId(TenantInfo.DEFAULT_SUBTENANT_ID);
        invoice.setDeletedFlag(Boolean.FALSE);
        return studentRecordInvoiceMapper.insert(invoice) > 0;
    }

    @Override
    public Boolean updateStudentRecordInvoice(Integer studentId, String studentRecordId, String invoiceId, StudentRecordInvoiceBo studentRecordInvoiceBo) {
        if (!StringUtils.hasText(studentRecordInvoiceBo.getInvoiceNo())) {
            studentRecordInvoiceBo.setInvoiceNo("-");
        }
        checkPermission(studentId, studentRecordId);
        var now = LocalDateTime.now();
        var account = AccountHolder.getRequiredAccountInfo();
        return studentRecordInvoiceMapper.update(
                null,
                new UpdateWrapper<StudentRecordInvoice>().lambda()
                        .eq(StudentRecordInvoice::getId, invoiceId)
                        .eq(StudentRecordInvoice::getStudentRecordId, studentRecordId)
                        .eq(StudentRecordInvoice::getDeletedFlag, Boolean.FALSE)
                        .set(StudentRecordInvoice::getInvoiceNo, studentRecordInvoiceBo.getInvoiceNo())
                        .set(StudentRecordInvoice::getInvoiceHeader, studentRecordInvoiceBo.getInvoiceHeader())
                        .set(StudentRecordInvoice::getInvoiceBalance, parsePrice(studentRecordInvoiceBo.getInvoiceBalanceFormatted()))
                        .set(StudentRecordInvoice::getModifiedBy, account.getEmail())
                        .set(StudentRecordInvoice::getModifiedDatetime, now)
        ) > 0;
    }

    @Override
    public Boolean deleteStudentRecordInvoice(Integer studentId, String studentRecordId, String invoiceId) {
        checkPermission(studentId, studentRecordId);
        var account = AccountHolder.getRequiredAccountInfo();
        var now = LocalDateTime.now();
        return studentRecordInvoiceMapper.update(
                null,
                new UpdateWrapper<StudentRecordInvoice>().lambda()
                        .eq(StudentRecordInvoice::getId, invoiceId)
                        .eq(StudentRecordInvoice::getStudentRecordId, studentRecordId)
                        .eq(StudentRecordInvoice::getDeletedFlag, Boolean.FALSE)
                        .set(StudentRecordInvoice::getDeletedFlag, Boolean.TRUE)
                        .set(StudentRecordInvoice::getDeletedBy, account.getEmail())
                        .set(StudentRecordInvoice::getDeletedDatetime, now)
        ) > 0;
    }
}
